package com.googlecode.imanager.client.action;

import com.googlecode.imanager.client.Container;
import com.googlecode.imanager.client.Control;
import com.googlecode.imanager.client.Document;
import com.googlecode.imanager.client.exception.ActionFailureException;
import com.googlecode.imanager.client.form.HasValidation;
import com.googlecode.imanager.client.form.Validator;

/**
 * @author wellsantos@wellsantos.com
 * @since 0.01
 */
public abstract class FlowAction extends Action implements Validator {

    private static final long serialVersionUID = 1L;
    
    @Override
    public void execute(Control sender) throws ActionFailureException, IllegalArgumentException {
        if (sender == null){
            throw new IllegalArgumentException("no sender specified");
        }
        try {
            doValidate(sender);
            doExecute(sender);

        } catch (Exception e) {
            onFailure(sender, e);
        }
    }

    public final void validate(Control sender) {
        if (sender != null){
            try {
                doValidate(sender);                
            } catch (Exception e) {
                onFailure(sender, e);
            }
        }
    }
    
    protected Control getFlowTarget(Control sender){
        Document doc = sender.getDocument();
        if (doc != null){
            return doc;
        }
        return sender.getRootParent();
    }

    protected void doValidate(Control sender) throws Exception {
        Control c = getFlowTarget(sender);
        if (c instanceof Container){
            ((Container) c).validateChildren();
        } 
        else if (c instanceof HasValidation) {
            ((HasValidation) c).validate();
        }
    }
    
    @Override
    protected void doExecute(Control sender) throws Exception {
        onSuccess(sender, null);
    }

    protected void onSuccess(Control sender, Object result){
    }
    
    protected void onFailure(Control sender, Throwable e){
        throw new ActionFailureException(this, e);
    }
    
}
